package com.winter.portal.server.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.winter.portal.api.dto.RoleDTO;
import com.winter.portal.api.dto.RoleResourceDTO;
import com.winter.portal.api.query.RoleQuery;
import com.winter.portal.api.vo.RoleResourceVO;
import com.winter.portal.api.vo.RoleVO;
import com.winter.portal.server.auth.cache.AuthorizationCacheService;
import com.winter.portal.server.entity.RoleEntity;
import com.winter.portal.server.entity.RoleResourceEntity;
import com.winter.portal.server.mapper.RoleMapper;
import com.winter.portal.server.service.ResourceService;
import com.winter.portal.server.service.RoleService;
import org.jzyan.framework.core.utils.ConvertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 系统角色表 服务实现类
 * </p>
 *
 * @author jzyan
 * @since 2023-04-11
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleEntity> implements RoleService {
    @Autowired
    private ResourceService resourceService;
    @Autowired
    private AuthorizationCacheService cacheService;

    @Override
    public IPage<RoleVO> table(RoleQuery roleQuery) {
        IPage page = new Page<>(roleQuery.getCurrent(), roleQuery.getLimit());
        if (roleQuery.getStartDate() == null || roleQuery.getEndDate() == null) {
            roleQuery.setStartDate(LocalDateTimeUtil.beginOfDay(LocalDateTime.now()));
            roleQuery.setEndDate(LocalDateTimeUtil.endOfDay(LocalDateTime.now()));
        }
        List<RoleEntity> content = baseMapper.page(page, roleQuery);
        return page.setRecords(ConvertUtil.convert(content, RoleVO.class));
    }

    @Override
    public void add(RoleDTO role) {
        RoleEntity roleEntity = ConvertUtil.convert(role, RoleEntity.class);
        baseMapper.insert(roleEntity);
    }

    @Override
    public List<RoleResourceVO> getResource(Serializable id) {
        List<RoleResourceEntity> list = resourceService.getRoleResource(id);
        List<RoleResourceVO> roleResourceList = new ArrayList<>();
        for (RoleResourceEntity result : list) {
            if (result.getParentId() == 0) {
                //调用方法给子类添加数据
                RoleResourceVO roleResourceVO = new RoleResourceVO();
                roleResourceVO.setId(result.getId());
                roleResourceVO.setTitle(result.getResourceName());
                roleResourceList.add(getMenuTree(roleResourceVO, list));
            }
        }
        return roleResourceList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addResource(RoleResourceDTO roleResource) {
        baseMapper.deleteRoleResourceByRoleId(roleResource.getId());
        if (!CollectionUtils.isEmpty(roleResource.getResourceIds())) {
            Map<String, Object> map = new HashMap<>(2);
            map.put("roleId", roleResource.getId());
            map.put("resourceIds", roleResource.getResourceIds());
            baseMapper.insertRoleResourceBatch(map);
        }
        // 清理访问权限缓存
        cacheService.removeAccess();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(RoleEntity roleEntity) {
        RoleEntity role = baseMapper.selectById(roleEntity.getId());
        updateById(roleEntity);
        if (!role.getEnabled().equals(roleEntity.getEnabled())) {
            baseMapper.updateUserRole(roleEntity);
            baseMapper.updateRoleResource(roleEntity);
            // 清理访问权限缓存，对应用户session
            if (roleEntity.getEnabled() == 0) {
                cacheService.removeAccess();
                Set<String> usernames = baseMapper.getUsernamesByRoleId(roleEntity.getId());
                for (String username : usernames) {
                    cacheService.removeToken(username);
                }
            }
        }
    }

    /**
     * 递归获取菜单Tree
     *
     * @param result
     * @param list
     * @return
     */
    private RoleResourceVO getMenuTree(RoleResourceVO result, List<RoleResourceEntity> list) {
        for (RoleResourceEntity resourceEntity : list) {
            //如果父类主键等于传过来实体类的ID
            if (resourceEntity.getParentId().equals(result.getId())) {
                RoleResourceVO roleResourceVO = new RoleResourceVO();
                roleResourceVO.setId(resourceEntity.getId());
                roleResourceVO.setTitle(resourceEntity.getResourceName());
                if (result.getChildren() == null) {
                    result.setChildren(new ArrayList<>());
                }
                // 递归调用
                result.getChildren().add(getMenuTree(roleResourceVO, list));
                if (CollectionUtils.isEmpty(roleResourceVO.getChildren())) {
                    roleResourceVO.setChecked(resourceEntity.getChecked());
                }
            }
        }
        return result;
    }
}
